﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

using RexToy.ExpressionLanguage;
using RexToy.UI.WinForm.Pmlx;

namespace RexToy.UI.WinForm.Controls
{
    public class DetailListView : System.Windows.Forms.ListView, ITemplateItem
    {
        private ExpressionLanguageEngine _el;
        public DetailListView()
        {
            _el = ExpressionLanguageEngine.CreateEngine(UIELEngineConfig.Config);
            this.MultiSelect = false;
            this.View = View.Details;
            this.FullRowSelect = true;
        }

        #region ITemplateItem Members
        public void ParseTemplate(PmlxNode template)
        {
            foreach (var node in template.ChildNodes)
            {
                var head = Activator.CreateInstance(node.MakeType()) as ColumnHeader;
                IReflector r = Reflector.Bind(head);
                foreach (PmlxNode attr in node.Attributes)
                {
                    attr.ApplyValue(r);
                }

                if (node.Value.BracketedBy(StringPair.Template_Bracket))
                {
                    head.BindExpression = node.Value.UnBracketing(StringPair.Template_Bracket);
                }
                else if (node.Value.BracketedBy(StringPair.Delayed_Template_Bracket))
                {
                    head.BindExpression = node.Value.UnBracketing(StringPair.Delayed_Template_Bracket);
                }
                else
                {
                    ThrowHelper.ThrowMustBindExpression();
                }

                this.Columns.Add(head);
            }
        }
        #endregion

        public void Bind<T>(IEnumerable<T> items)
        {
            List<DetailListViewItem<T>> l = new List<DetailListViewItem<T>>();
            foreach (T item in items)
            {
                DetailListViewItem<T> lvi = RenderItem(item);
                lvi.Item = item;
                l.Add(lvi);
            }
            BeginUpdate();
            this.Items.AddRange(l.ToArray());
            EndUpdate();
        }

        private DetailListViewItem<T> RenderItem<T>(T item)
        {
            string[] strArray = new string[Columns.Count];
            _el.Assign(ControlConstant.EVAL_CTX_ITEM, item);
            for (int i = 0; i < Columns.Count; i++)
            {
                ColumnHeader header = Columns[i] as ColumnHeader;
                strArray[i] = _el.Eval(header.BindExpression).ToString();
            }
            return new DetailListViewItem<T>(strArray);
        }

        public IEnumerable<T> GetSelectedItems<T>()
        {
            foreach (DetailListViewItem<T> lvi in this.SelectedItems)
            {
                yield return lvi.Item;
            }
        }

        public T GetSelectedItem<T>()
        {
            Assertion.IsFalse(this.MultiSelect, "Multi select is enabled.");
            switch (this.SelectedItems.Count)
            {
                case 0:
                    return default(T);

                default:
                    DetailListViewItem<T> lvi = this.SelectedItems[0] as DetailListViewItem<T>;
                    return lvi.Item;
            }
        }

        public IEnumerable<T> GetCheckedItems<T>()
        {
            Assertion.IsTrue(this.CheckBoxes, "Check box is not enabled.");
            foreach (DetailListViewItem<T> lvi in this.CheckedItems)
            {
                yield return lvi.Item;
            }
        }
    }
}
